﻿using System;
using System.Collections;
using System.Xml;
using InfoJetSoft.Service.Entity;
using InfoJetSoft.Service.Util;

namespace InfoJetSoft.Service.Worker
{
	
	class XmlXmlToEditInsertWorker
	{
		
		public static int Insert_First = 0;
		
		public static int Insert_Last = 1;
		
		public static int Insert_Before = 2;
		
		public static int Insert_After = 3;
		
		public static void  insert(Form form, XmlToEditContext context, int pos)
		{
			XmlDocument doc = context.Doc;
			
			XmlNode parentNode = context.ParentNode;
			XmlNode itemNode = context.ItemNode;
			ChooseFragment existChooseFragment = context.ExistChooseFragment;
			ArrayList insertXmlNodeList = existChooseFragment.XmlNodeList;
			
			if (parentNode is XmlElement)
			{
				XmlElement parentElement = (XmlElement) parentNode;
				foreach (XmlNode insertNode in insertXmlNodeList)
				{
					if (insertNode is XmlAttribute)
					{
						//检查parentElement是否可以具有Attribute.
						XmlAttribute attribute = (XmlAttribute) insertNode;
						if (SchemaUtil.canSetAttr(form, parentElement, attribute))
						{
							XmlAttribute insertAttribute = doc.CreateAttribute(attribute.Name, attribute.NamespaceURI);
							insertAttribute.Value = attribute.Value;
							parentElement.SetAttributeNode(insertAttribute);
						}
					}
					else if (insertNode is XmlElement)
					{
						//检查Element在parentElement中子节点中的位置.
						XmlElement insertElement = (XmlElement) insertNode;
						XmlElement cloneInsertElement = CloneUtil.cloneElement(form.XmlDoc, insertElement);
						if (SchemaUtil.getChildElementCount(parentElement) > 0)
						{
							XmlElement insertedElement = insertElementByPos(form, parentElement, cloneInsertElement, pos, itemNode);
							if( insertedElement != null )	//CID 0008 //2008.06.11 //if
							{
								EmptyXmlnsFormater.formatEmptyXmlns( insertedElement );
								form.NewStructureNode = insertedElement;

                                //CID 1149 //2012.03.28 //Begin
                                FormBuildFieldListByXMLDocWorker.buildFieldListByXMLDoc(form, true);
                                //CID 1149 //2012.03.28 //End

								//检查是否需要更新MasterDetail上下文。
								FormMasterDetailContextWorker.updateMasterDetialContext( form, context, insertedElement, false );
								//CID 0473 //2009.12.14 //Begin
								XmlToEditUtil.domEventHandler( form, context, insertedElement );
                                //CID 0907 //2011.05.13 //Begin
								FormCalculatedFieldWorker.calcaulteGroupNode( form, insertedElement, null, false );
                                //CID 0907 //2011.05.13 //End
								//CID 0473 //2009.12.14 //End
								string path = DOMUtil.getNodePath( insertedElement );
								FormCodeDispatchWorker.OnAfterChange( form, path, insertedElement, FormCodeDispatchWorker.Updated, false );
								//CID 0007 //2008.06.11 //Begin
								XFileAttachmentDecoder.try2CacheFile( form, context.XmlToEdit, insertedElement );
								//CID 0007 //2008.06.11 //End
							}
							//CID 0008 //2008.06.12 //Begin
							else
							{
								string cannotInsertSectionOrRowMessage = form.Manifest.FormConfiguration.GetCannotInsertSectionOrRowMessage( context.XmlToEdit.Name );
								if( cannotInsertSectionOrRowMessage == null )
								{
									cannotInsertSectionOrRowMessage = MessageUtil.CannotInsertSectionOrRowMessage();
								}
								form.ModalMessageList.Add( cannotInsertSectionOrRowMessage );
							}
							//CID 0008 //2008.06.12 //End
						}
						else
						{
							if (SchemaUtil.canAppendChild(form, parentElement, cloneInsertElement))
							{
								parentElement.AppendChild(cloneInsertElement);
								EmptyXmlnsFormater.formatEmptyXmlns( cloneInsertElement );
								form.NewStructureNode = cloneInsertElement;

                                //CID 1149 //2012.03.28 //Begin
                                FormBuildFieldListByXMLDocWorker.buildFieldListByXMLDoc(form, true);
                                //CID 1149 //2012.03.28 //End

								//检查是否需要更新MasterDetail上下文。
								FormMasterDetailContextWorker.updateMasterDetialContext( form, context, cloneInsertElement, false );
								//CID 0473 //2009.12.14 //Begin
								XmlToEditUtil.domEventHandler( form, context, cloneInsertElement );
                                //CID 0907 //2011.05.13 //Begin
								FormCalculatedFieldWorker.calcaulteGroupNode( form, cloneInsertElement, null, false );
                                //CID 0907 //2011.05.13 //End
                                //CID 0473 //2009.12.14 //End
								string path = DOMUtil.getNodePath( cloneInsertElement );
								FormCodeDispatchWorker.OnAfterChange( form, path, cloneInsertElement, FormCodeDispatchWorker.Updated, false );
								//CID 0007 //2008.06.11 //Begin
								XFileAttachmentDecoder.try2CacheFile( form, context.XmlToEdit, cloneInsertElement );
								//CID 0007 //2008.06.11 //End
							}
							//CID 0008 //2008.06.12 //Begin
							else
							{
								string cannotInsertSectionOrRowMessage = form.Manifest.FormConfiguration.GetCannotInsertSectionOrRowMessage( context.XmlToEdit.Name );
								if( cannotInsertSectionOrRowMessage == null )
								{
									cannotInsertSectionOrRowMessage = MessageUtil.CannotInsertSectionOrRowMessage();
								}
								form.ModalMessageList.Add( cannotInsertSectionOrRowMessage );
							}
							//CID 0008 //2008.06.12 //End
						}
					}
				}
			}
		}
		
		private static XmlElement  insertElementByPos(Form form, XmlElement parentElement, XmlElement insertElement, int pos, XmlNode itemNode)
		{
			if (pos == Insert_First)
			{
				return insertElementFirst(form, parentElement, insertElement);
			}
			else if (pos == Insert_Last)
			{
				return insertElementLast(form, parentElement, insertElement);
			}
			else if (pos == Insert_Before)
			{
				return insertElementBefore(form, parentElement, insertElement, itemNode);
			}
			else if (pos == Insert_After)
			{
				return insertElementAfter(form, parentElement, insertElement, itemNode);
			}
			return null;
		}
		
		private static XmlElement  insertElementFirst(Form form, XmlElement parentElement, XmlElement insertElement)
		{
			XmlNodeList childList = parentElement.ChildNodes;
			foreach (XmlNode node in childList)
			{
				if (node is XmlElement)
				{
					XmlElement itemElement = (XmlElement) node;
					if (SchemaUtil.canInsertBefore(form, parentElement, insertElement, itemElement))
					{
						parentElement.InsertBefore(insertElement, itemElement);
						return insertElement;
					}
				}
			}
			if (SchemaUtil.canAppendChild(form, parentElement, insertElement))
			{
				parentElement.AppendChild(insertElement);
				return insertElement;
			}
			return null;
		}
		
		private static XmlElement insertElementLast(Form form, XmlElement parentElement, XmlElement insertElement)
		{
			string itemNodeFilter = insertElement.Name;
			XmlNodeList itemXmlNodeList = DOMUtil.selectNodes(parentElement, itemNodeFilter, 0, form.XmlNsResolver);
			if (itemXmlNodeList.Count > 0)
			{
				XmlElement lastItemElement = (XmlElement) itemXmlNodeList[itemXmlNodeList.Count - 1];
				if(SchemaUtil.canInsertAfter(form, parentElement, insertElement, lastItemElement)){
					parentElement.InsertAfter( insertElement, lastItemElement );
					return insertElement;
				}
			}
			else
			{
				insertElementFirst(form, parentElement, insertElement);
				return insertElement;
			}
			return null;
		}
		
		private static XmlElement insertElementBefore(Form form, XmlElement parentElement, XmlElement insertElement, XmlNode itemNode)
		{
			XmlNodeList childList = parentElement.ChildNodes;
			foreach (XmlNode node in childList)
			{
				//这时候有可能找不到相等的item node.
				if (node.Equals(itemNode) && node is XmlElement)
				{
					XmlElement itemElement = (XmlElement) node;
					if (SchemaUtil.canInsertBefore(form, parentElement, insertElement, itemElement))
					{
						parentElement.InsertBefore(insertElement, itemElement);
						return insertElement;
					}
					break;
				}
			}
			return null;
		}
		
		private static XmlElement insertElementAfter(Form form, XmlElement parentElement, XmlElement insertElement, XmlNode itemNode)
		{
			XmlNodeList childList = parentElement.ChildNodes;
			foreach (XmlNode node in childList)
			{
				if (node.Equals(itemNode))
				{
					XmlElement itemElement = (XmlElement) node;
					if (SchemaUtil.canInsertAfter(form, parentElement, insertElement, itemElement)) {
						parentElement.InsertAfter(insertElement, itemElement);
						return insertElement;
					}
					break;
				}
			}
			return null;
		}
	}
}